package cn.mothin.frame.listener;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

import cn.mothin.frame.core.annotation.BackgroundRobot;
import cn.mothin.frame.core.db.SqlHelper;
import cn.mothin.frame.core.interfaces.IBackgroundRobot;
import cn.mothin.frame.util.SpringUtil;

@SuppressWarnings("rawtypes")
@Component("7e44bd8d-b06f-4183-8525-127ce4a11ffc")
public class BackgroundRobotManager implements ApplicationListener {
	private final Log log = LogFactory.getLog(PermissionRobotListener.class);
	@Autowired
	private SqlHelper sqlHelper;

	private Map<String, Integer> intervalMap = new HashMap<String, Integer>();
	private Map<String, IBackgroundRobot> interfaceMap = new HashMap<String, IBackgroundRobot>();
	private Map<String, Long> runMap = new HashMap<String, Long>();

	private Map<String, IBackgroundRobot> robotsMode0 =  new HashMap<String, IBackgroundRobot>();
	private Map<String, IBackgroundRobot> robotsMode1 =  new HashMap<String, IBackgroundRobot>();

	private void findRobots() {
		long now=System.currentTimeMillis();
		List<IBackgroundRobot> robots = SpringUtil
				.getClassListWithInterface(IBackgroundRobot.class);
		for (IBackgroundRobot robot : robots) {
			Class<?> c = robot.getClass();
			String className=c.getName();
			if(className.contains("$$")){
				String[] ss=className.split("\\$\\$");
				String cn=ss[0];
				try {
					c=Class.forName(cn);
				} catch (ClassNotFoundException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			if (c.isAnnotationPresent(BackgroundRobot.class)) {
				BackgroundRobot backgroundRobot = c.getAnnotation(BackgroundRobot.class);
				String id=backgroundRobot.id();
				int interval=backgroundRobot.interval();
				switch (backgroundRobot.runMode()) {
				case BackgroundRobot.RUN_MODE_ONCE:
					robotsMode0.put(id, robot);
					break;
				case BackgroundRobot.RUN_MODE_EVERY_REBOOT:
					robotsMode1.put(id, robot);
					break;
				case BackgroundRobot.RUN_MODE_LOOP:
					if(interval>0){
						interfaceMap.put(id, robot);
						runMap.put(id, now);
						intervalMap.put(id, interval*1000);
					}
					break;
				}
			}
		}
	}
	
	private void runRobot(final IBackgroundRobot robot){
		try{
			new Thread(new Runnable() {
				@Override
				public void run() {
					try{
						robot.run();
					}catch(Throwable t){
						log.error(t);
					}
				}
			}).start();
		}catch(Throwable t){
			log.error(t);
		}
	}
	
	private void startRobot0(){
		if(robotsMode0.size()==0){
			return;
		}
		
		String sql="SELECT id FROM background_robot_record";
		List<String> list = sqlHelper.queryForList(String.class, sql);
		
		Date now=new Date(System.currentTimeMillis());
		sql="INSERT INTO background_robot_record(id,runTime) VALUES(?,?);";
		for (String id : robotsMode0.keySet()) {
			if(!list.contains(id)){
				try{
					sqlHelper.execute(sql, id,now);
					runRobot(robotsMode0.get(id));
				}catch(Throwable t){
					log.error(t);
				}
			}
		}
	}
	
	private long startRobot2(){
		if(runMap.size()<=0){
			return -1;
		}
		
		long now=System.currentTimeMillis();
		long min=Long.MAX_VALUE;
		for (String id : interfaceMap.keySet()) {
			long l=runMap.get(id);
			long next=l;
			int interval=intervalMap.get(id);
			if(now>=l){
				next+=interval;
				runMap.put(id, next);
				runRobot(interfaceMap.get(id));
			}
			if(min>next){
				min=next;
			}
		}
		if(min==Long.MAX_VALUE){
			return -1;
		}
		return min-now;
	}

	@Override
	public void onApplicationEvent(ApplicationEvent arg0) {
	    Thread t = new Thread(new Runnable() {
			@Override
			public void run() {
				findRobots();
				// mode 0 启动
				startRobot0();
				// mode 1 启动
				if(robotsMode1.size()>0){
					for (String id : robotsMode1.keySet()) {
						runRobot(robotsMode1.get(id));
					}
				}
				// mode 2 启动
				if(interfaceMap.size()>0){
					List<String> ids=new ArrayList<String>();
					for (String id : interfaceMap.keySet()) {
						try{
							if(!interfaceMap.get(id).init()){
								ids.add(id);
							}
						}catch(Throwable t){
							log.error(t);
						}
					}
					if(ids.size()>0){
						for(String id:ids){
							interfaceMap.remove(id);
							runMap.remove(id);
						}
					}
					
					long time=-1;
					while (true) {
						time=startRobot2();
						if(time<=0){
							System.out.println("startRobot2()=-1");
							break;
						}
						try {
							Thread.sleep(time);
						} catch (InterruptedException e) {
							
						}
					}
				}
			}
		});
	    t.setDaemon(true);
	    t.start();
	}
}
